<?php

namespace App\Http\Controllers;

use App\Models\Answer;
use App\Models\Category;
use App\Models\Question;
use App\Models\Test;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;

class ZiceController extends Controller
{
    /**
     * 考题所需字段
     *
     * @var array
     */
    public $questionColumns = [
        'id',
        'question',
        'type',
        'option_1',
        'option_2',
        'option_3',
        'option_4',
    ];

    /**
     * @return \Illuminate\Contracts\Support\Renderable|\Illuminate\Http\RedirectResponse
     */
    public function index()
    {
        /** @var User $user 考生 */
        $user = Auth::user();

        // 考试机会已用完（暂不限制）
        // abort_if(! $user->canTest(), 403, '您今天已参与过自测，请明天再来，感谢您的参与！');

        // 正在回答的题目序号
        $index = 1;

        // 如果有考试进行中，直接获取考题，否则开始一次新的考试
        if ($test = $user->currentTest()) {
            // 超时自动交卷
            if ($test->created_at->addMinutes($test->test_time)->lt(now())) {
                $test->submit();

                return redirect()->route('guess');
            }

            // 获取本次考试的考题
            $questions = Question::getFromCache($test->questions);

            // 获取本次考试考生已提交的答案
            $answers = Test::getAnswersFromCache($user->id, $test->id);

            // 填充用户答案
            $questions = collect($questions)->map(function (Question $question) use ($answers) {
                /** @var Answer|array $answer */
                $answer = $answers->get($question->id);

                $question->setAttribute('user_answer', $answer ? $answer['answer'] : []);

                return $question;
            });

            $index = $answers->count() + 1;
        } else {
            // 抽取考题
            $questions = Question::getFromCache($this->extractQuestionIds());

            // 没有考题
            abort_if(! count($questions), 403, '没有提取到考题，请联系管理员！');

            // 开始考试
            $test = $this->createTest($user, $questions);
        }

        // 剩余时间（秒）
        $timeLeft = $test->created_at->addMinutes($test->test_time)->diffInSeconds(now());

        // 数据：用户、考试、题目、正在回答的题目序号
        return view('h5.guess', compact('user', 'test', 'questions', 'index', 'timeLeft'));
    }

    public function submit()
    {
        /** @var User $user 考生 */
        $user = Auth::user();

        $test = $user->currentTest();

        if ($test) {
            $test->submit();
        }
    }

    /**
     * 从缓存中抽取题目 ID
     *
     * @return array
     */
    protected function extractQuestionIds()
    {
        return Cache::store()->tags('tests')->remember(rand(1, 100), 600, function () {
            return $this->generateQuestions();
        });
    }

    /**
     * 根据分类随机生成考题
     *
     * @return array
     */
    protected function generateQuestions()
    {
        // 每种分类根据选题数随机取出
        return Category::getFromCache()->reduce(function (array $carry, Category $category) {
            // 当前分类未选题直接跳过
            if (! $category->selected_count) {
                return $carry;
            }

            // 按随机顺序取出当前分类选题数量的题目
            $question = $category->questions()
                ->inRandomOrder()
                ->limit($category->selected_count)
                ->pluck('id')
                ->sort()
                ->all();

            return array_merge($carry, $question);
        }, []);
    }

    /**
     * 开始一次新的考试
     *
     * @param User $user
     * @param array $questions
     * @return Test
     */
    protected function createTest(User $user, array $questions)
    {
        // 获取配置
        $setting = admin_setting();

        $test = new Test();

        $test->unit_id = $user->unit_id;
        $test->question_count = count($questions);
        $test->pre_score = $setting->get('pre_score');
        $test->test_time = $setting->get('test_time');
        $test->questions = implode(',', array_keys($questions));

        $user->test()->save($test);

        // 缓存当前考试信息
        Cache::put('test_for_user_' . $user->id, $test, $test->test_time * 60);

        // 清除考生之前考试提交的答案
        Answer::query()->where('user_id', $user->id)->delete();

        return $test;
    }
}
